#include <sys/mman.h>
#include <sys/time.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <auratypes.h>
#include <auraplus.h>

EXTERN_C int AuraMemoryProtectionConvertToLinux(Aura_MemoryProtection protect)
{
    int iRetProtect;

    switch(protect)
    {
        case Aura_MemoryProtection_Read:
            iRetProtect = PROT_READ;
            break;

        case Aura_MemoryProtection_Write:
            iRetProtect = PROT_WRITE;
            break;

        case Aura_MemoryProtection_Exec:
            iRetProtect = PROT_EXEC;
            break;

        case Aura_MemoryProtection_RW:
        case Aura_MemoryProtection_RWIO:
            iRetProtect = PROT_READ|PROT_WRITE;
            break;

        case Aura_MemoryProtection_RX:
            iRetProtect = PROT_READ|PROT_EXEC;
            break;

        case Aura_MemoryProtection_RWX:
            iRetProtect = PROT_READ|PROT_EXEC|PROT_EXEC;
            break;

        case Aura_MemoryProtection_IO:
        default:
            iRetProtect = PROT_READ;
            break;
    }

    return iRetProtect;
}

EXTERN_C Aura_ECode MaskSignal(sigset_t *pSigNewMask, sigset_t *pSigOldMask)
{
    sigaddset( pSigNewMask, SIGINT );
    sigaddset( pSigNewMask, SIGALRM );
    sigaddset( pSigNewMask, SIGUSR1 );

    //Mask signal
    if(0 > sigprocmask(SIG_BLOCK, pSigNewMask, pSigOldMask)){
        PERROR("Error: Mask Signal failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_ARGUMENT;
    }

    return AURA_NOERROR;

}

EXTERN_C void UnmaskSignal(sigset_t *pSigOldMask)
{
    sigprocmask(SIG_SETMASK, pSigOldMask, AURA_NULL);
}

EXTERN_C Aura_ECode SetMilliTimer(Aura_Millisecond time)
{
    int ret;
    struct itimerval timeval;

    timeval.it_interval.tv_sec  = 0;
    timeval.it_interval.tv_usec = 0;

    timeval.it_value.tv_sec  = time/1000;
    timeval.it_value.tv_usec = (time%1000)*1000;

    ret = setitimer(ITIMER_REAL, &timeval, AURA_NULL);
    if(-1 == ret){
        PERROR("Error: Set timer failed! \
        file:%s. line:%d. \n",
        __FILE__, __LINE__);
        return AURA_E_INVALID_OPERATION;
    }

    return AURA_NOERROR;
}

EXTERN_C Aura_ECode SetTimeOut(Aura_Millisecond timeOut, Aura_WaitResult * pResult)
{
    Aura_ECode ec;
    if(AURA_INFINITE != timeOut){
        if(0 == timeOut){
            if(AURA_NULL != pResult){
                *pResult = Aura_WaitResult_TimedOut;
            }
            return AURA_NOERROR;
        }
        ec = SetMilliTimer(timeOut);
        if(AURA_FAILED(ec)){
            PERROR("Error: Mutex Lock failed! \
            file:%s. line:%d. \n",
            __FILE__, __LINE__);
            return ec;
        }
    }
    return AURA_NOERROR;
}
